using System;
using System.Text;
using System.Drawing;
using FastReport.Utils;

namespace FastReport.Barcode
{
    /// <summary>
    /// Generates the UPC E0 barcode.
    /// </summary>
    public class BarcodeUPC_E0 : BarcodeEAN
    {
        // UPC E Parity Pattern Table , Number System 0
        internal static string[,] tabelle_UPC_E0 = {
      {"E", "E", "E", "o", "o", "o" },    // 0
      {"E", "E", "o", "E", "o", "o" },    // 1
      {"E", "E", "o", "o", "E", "o" },    // 2
      {"E", "E", "o", "o", "o", "E" },    // 3
      {"E", "o", "E", "E", "o", "o" },    // 4
      {"E", "o", "o", "E", "E", "o" },    // 5
      {"E", "o", "o", "o", "E", "E" },    // 6
      {"E", "o", "E", "o", "E", "o" },    // 7
      {"E", "o", "E", "o", "o", "E" },    // 8
      {"E", "o", "o", "E", "o", "E" }     // 9
    };

        internal override void DrawText(IGraphics g, string barData)
        {
            DrawString(g, -8, -2, "0", true);

            // parts of pattern: 3 + 24 + 6
            float x1 = GetWidth(pattern.Substring(0, 3));
            float x2 = GetWidth(pattern.Substring(0, 3 + 24));
            DrawString(g, x1, x2, barData.Substring(0, 6));

            x1 = GetWidth(pattern) + 1;
            x2 = x1 + 7;
            DrawString(g, x1, x2, barData.Substring(6, 1), true);
        }

        internal override string GetPattern()
        {
            text = DoCheckSumming(text, 7);
            int c = CharToInt(text[6]);

            // Startcode
            string result = "A0A";

            for (int i = 0; i <= 5; i++)
            {
                if (tabelle_UPC_E0[c, i] == "E")
                {
                    for (int j = 0; j <= 3; j++)
                        result += tabelle_EAN_C[CharToInt(text[i])][3 - j];
                }
                else
                    result += tabelle_EAN_A[CharToInt(text[i])];
            }

            // Stopcode
            result += "0A0A0A";
            return result;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="BarcodeUPC_E0"/> class with default settings.
        /// </summary>
        public BarcodeUPC_E0()
        {
            extra1 = 8;
            extra2 = 8;
        }
    }

    /// <summary>
    /// Generates the UPC E1 barcode.
    /// </summary>
    public class BarcodeUPC_E1 : BarcodeUPC_E0
    {
        internal override string GetPattern()
        {
            text = DoCheckSumming(text, 7);
            int c = CharToInt(text[6]);

            // Startcode
            string result = "A0A";
            for (int i = 0; i <= 5; i++)
            {
                if (tabelle_UPC_E0[c, i] == "E")
                    result += tabelle_EAN_A[CharToInt(text[i])];
                else
                {
                    for (int j = 0; j <= 3; j++)
                        result += tabelle_EAN_C[CharToInt(text[i])][3 - j];
                }
            }

            // Stopcode
            result += "0A0A0A";
            return result;
        }
    }

    /// <summary>
    /// Generates the UPC A barcode.
    /// </summary>
    public class BarcodeUPC_A : BarcodeUPC_E0
    {
        internal override void DrawText(IGraphics g, string barData)
        {
            DrawString(g, -8, -2, barData.Substring(0, 1), true);

            // parts of pattern: 7 + 20 + 5 + 20 + 7
            float x1 = GetWidth(pattern.Substring(0, 7));
            float x2 = GetWidth(pattern.Substring(0, 7 + 20));
            DrawString(g, x1, x2, barData.Substring(1, 5));

            x1 = GetWidth(pattern.Substring(0, 7 + 20 + 5));
            x2 = GetWidth(pattern.Substring(0, 7 + 20 + 5 + 20));
            DrawString(g, x1, x2, barData.Substring(6, 5));

            x1 = GetWidth(pattern) + 1;
            x2 = x1 + 7;
            DrawString(g, x1, x2, barData.Substring(11, 1), true);
        }

        internal override string GetPattern()
        {
            text = DoCheckSumming(text, 12);

            //Startcode
            string result = "A0A";
            for (int i = 0; i <= 5; i++)
            {
                string code = tabelle_EAN_A[CharToInt(text[i])];
                result += i == 0 ? MakeLong(code) : code;
            }

            //Trennzeichen
            result += "0A0A0";
            for (int i = 6; i <= 11; i++)
            {
                string code = tabelle_EAN_C[CharToInt(text[i])];
                result += i == 11 ? MakeLong(code) : code;
            }

            //Stopcode
            return result + "A0A";
        }
    }

    /// <summary>
    /// Generates the 2-digit supplement barcode.
    /// </summary>
    public class BarcodeSupplement2 : BarcodeUPC_E0
    {
        internal string getSupp(string Nr)
        {
            int sum = 0;
            string tmp = Nr.Substring(0, Nr.Length - 1);

            int fak = tmp.Length;

            for (int i = 0; i < tmp.Length; i++)
            {
                sum += int.Parse(tmp[i].ToString()) * ((fak % 2) == 0 ? 9 : 3);
                fak--;
            }

            sum = ((sum % 10) % 10) % 10;
            return tmp + sum.ToString();
        }

        internal override void DrawText(IGraphics g, string barData)
        {
            DrawString(g, 0, drawArea.Width, barData);
        }

        internal override string GetPattern()
        {
            text = SetLen(2);

            int i32 = int.Parse(text);
            string mS;

            switch (i32 % 4)
            {
                case 0:
                    mS = "oo";
                    break;
                case 1:
                    mS = "oE";
                    break;
                case 2:
                    mS = "Eo";
                    break;
                case 3:
                    mS = "EE";
                    break;
                default:
                    mS = "";
                    break;
            }

            string tmp = getSupp(text + "0");

            string result = "506";   // Startcode
            for (int i = 0; i <= 1; i++)
            {
                if (mS[i] == 'E')
                {
                    for (int j = 0; j <= 3; j++)
                        result += tabelle_EAN_C[CharToInt(tmp[i])][3 - j];
                }
                else
                    result += tabelle_EAN_A[CharToInt(tmp[i])];

                if (i < 1)
                    result += "05"; // character delineator 
            }

            return result;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="BarcodeSupplement2"/> class with default settings.
        /// </summary>
        public BarcodeSupplement2()
        {
            textUp = true;
            extra1 = 0;
            extra2 = 0;
        }
    }

    /// <summary>
    /// Generates the 5-digit supplement barcode.
    /// </summary>
    internal class BarcodeSupplement5 : BarcodeSupplement2
    {
        internal override string GetPattern()
        {
            text = SetLen(5);
            string tmp = getSupp(text + "0");
            char c = tmp[5];

            string result = "506";   // Startcode

            for (int i = 0; i <= 4; i++)
            {
                if (tabelle_UPC_E0[CharToInt(c), 1 + i] == "E")
                {
                    for (int j = 0; j <= 3; j++)
                        result += tabelle_EAN_C[CharToInt(tmp[i])][3 - j];
                }
                else
                    result += tabelle_EAN_A[CharToInt(tmp[i])];

                if (i < 4)
                    result += "05"; // character delineator 
            }

            return result;
        }
    }
}
